//
// Created on 2023/6/7.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef AVCODEC_NAPI_UTILS_H_
#define AVCODEC_NAPI_UTILS_H_
#include "avcodec_log.h"
#include "napi/native_api.h"
#include <js_native_api_types.h>
#include <memory>
#include <string>

#define IMG_IS_OK(x) ((x) == napi_ok)
#define IMG_NOT_NULL(p) ((p) != nullptr)
#define IMG_IS_READY(x, p) (IMG_IS_OK(x) && IMG_NOT_NULL(p))

#define IMG_NAPI_CHECK_RET_D(x, res, msg) \
do \
{ \
    if (!(x)) \
    { \
        msg; \
        return (res); \
    } \
} while (0)

#define IMG_NAPI_CHECK_RET(x, res) \
do \
{ \
    if (!(x)) \
    { \
        return (res); \
    } \
} while (0)

#define IMG_JS_ARGS(env, info, status, argc, argv, thisVar) \
do \
{ \
    status = napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr); \
} while (0)

#define IMG_JS_NO_ARGS(env, info, status, thisVar) \
do \
{ \
    status = napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr); \
} while (0)

#define IMG_CREATE_CREATE_ASYNC_WORK(env, status, workName, exec, complete, aContext, work) \
do \
{ \
    napi_value _resource = nullptr; \
    napi_create_string_utf8((env), (workName), NAPI_AUTO_LENGTH, &_resource); \
    (status) = napi_create_async_work(env, nullptr, _resource, (exec), \
            (complete), static_cast<void*>((aContext).get()), &(work)); \
    if ((status) == napi_ok) { \
        (status) = napi_queue_async_work((env), (work)); \
        if ((status) == napi_ok) { \
            (aContext).release(); \
        } \
    } \
} while (0)

#define IMG_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))

#define GET_BUFFER_BY_NAME(root, name, res, len) ImageNapiUtils::GetBufferByName(env, (root), (name), &(res), &(len))
#define GET_UINT32_BY_NAME(root, name, res) ImageNapiUtils::GetUint32ByName(env, (root), (name), &(res))
#define GET_INT32_BY_NAME(root, name, res) ImageNapiUtils::GetInt32ByName(env, (root), (name), &(res))
#define GET_BOOL_BY_NAME(root, name, res) ImageNapiUtils::GetBoolByName(env, (root), (name), &(res))
#define GET_NODE_BY_NAME(root, name, res) ImageNapiUtils::GetNodeByName(env, (root), (name), &(res))

#define STATIC_EXEC_FUNC(name) static void name ## Exec(napi_env env, void *data)
#define STATIC_COMPLETE_FUNC(name) static void name ## Complete(napi_env env, napi_status status, void *data)

#define DECORATOR_HILOG(op, fmt, args...) \
do { \
    op(LABEL, fmt, ##args); \
} while (0)

#define IMAGE_ERR(fmt, ...) DECORATOR_HILOG(HiLog::Error, fmt, ##__VA_ARGS__)
#ifdef IMAGE_DEBUG_FLAG
#define IMAGE_INFO(fmt, ...) DECORATOR_HILOG(HiLog::Info, fmt, ##__VA_ARGS__)
#define IMAGE_DEBUG(fmt, ...) DECORATOR_HILOG(HiLog::Debug, fmt, ##__VA_ARGS__)
#define IMAGE_FUNCTION_IN(fmt, ...) DECORATOR_HILOG(HiLog::Info, fmt "%{public}s IN", __FUNCTION__, ##__VA_ARGS__)
#define IMAGE_FUNCTION_OUT(fmt, ...) DECORATOR_HILOG(HiLog::Info, fmt "%{public}s OUT", __FUNCTION__, ##__VA_ARGS__)
#define IMAGE_LINE_IN(fmt, ...) DECORATOR_HILOG(HiLog::Info, fmt "%{public}d IN", __LINE__, ##__VA_ARGS__)
#define IMAGE_LINE_OUT(fmt, ...) DECORATOR_HILOG(HiLog::Info, fmt "%{public}d OUT", __LINE__, ##__VA_ARGS__)
#else
#define IMAGE_INFO(fmt, ...)
#define IMAGE_DEBUG(fmt, ...)
#define IMAGE_FUNCTION_IN(fmt, ...)
#define IMAGE_FUNCTION_OUT(fmt, ...)
#define IMAGE_LINE_IN(fmt, ...)
#define IMAGE_LINE_OUT(fmt, ...)
#endif

#define AVCODEC_CHECK_AND_RETURN_RET_LOG(cond, ret, fmt, ...)      \
    do {                                                        \
        if (!(cond)) {                                          \
            (void)AVCODEC_LOGE(fmt, ##__VA_ARGS__);             \
            return ret;                                         \
        }                                                       \
    } while (0)

#define AVCODEC_CHECK_AND_RETURN_LOG(cond, fmt, ...)               \
    do {                                                        \
        if (!(cond)) {                                          \
            (void)AVCODEC_LOGE(fmt, ##__VA_ARGS__);             \
            return;                                             \
        }                                                       \
    } while (0)
#define AVCODEC_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar)                       \
    do {                                                                                        \
        void* data;                                                                             \
        status = napi_get_cb_info(env, info, nullptr, nullptr, &(thisVar), &data);              \
    } while (0)
namespace OHOS {
namespace Media {
const int ARGS0 = 0;
const int ARGS1 = 1;
const int ARGS2 = 2;
const int ARGS3 = 3;
const int ARGS4 = 4;
const int PARAM0 = 0;
const int PARAM1 = 1;
const int PARAM2 = 2;
const int PARAM3 = 3;
struct AsyncCallbackInfo {
    napi_env env;
    napi_async_work asyncWork;
    napi_deferred deferred;
    napi_callback_info info;
};

class AvCodecNapiUtils {
public:
    static bool getNapiCharArrFromUint8Arr(napi_env env, napi_value value, uint8_t **resultBuf, int bufLen, int &realLen,
                                           bool isCpy);
    static bool getNapiInt64Value(napi_env env, napi_value value, int64_t &result);
    static bool getNapiInt32Value(napi_env env, napi_value value, int32_t &result);
    static std::string getNapiStringValue(napi_env env, napi_value value);
    static bool getObjPropInt32Value(napi_env env, napi_value value, const char *prop, int32_t &outVal);
    static std::string getObjPropStringValue(napi_env env, napi_value value, const char *prop);
    static bool createNapiInt32Value(napi_env env, int32_t value, napi_value &result);
    static bool createNapiStringValue(napi_env env, std::string value,napi_value &result);
    static bool setNapiObjInt32Prop(napi_env env, const char *prop,int32_t value, napi_value &obj);
    static bool setNapiObjStringProp(napi_env env,const char *prop,std::string value, napi_value &obj);
    static bool CreateArrayBuffer(napi_env env, void* src, size_t srcLen, napi_value *res);
    static bool CreateArrayBuffer1(napi_env env, void* src, size_t srcLen, napi_value *res);
    static napi_valuetype getType(napi_env env, napi_value root);
};
}//namespace Media
}//namespace OHOS


#endif //AVCODEC_NAPI_UTILS_H_
